﻿using System;
using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Reflection;
using HslCommunication.Serial;

namespace HslCommunication.Profinet.Siemens
{
	/// <summary>
	/// 西门子的PPI协议，适用于s7-200plc，注意，由于本类库的每次通讯分成2次操作，内部增加了一个同步锁，所以单次通信时间比较久，另外，地址支持携带站号，例如：s=2;M100<br />
	/// Siemens' PPI protocol is suitable for s7-200plc. Note that since each communication of this class library is divided into two operations, 
	/// and a synchronization lock is added inside, the single communication time is relatively long. In addition, 
	/// the address supports carrying the station number, for example : S=2;M100
	/// </summary>
	/// <remarks>
	/// 适用于西门子200的通信，非常感谢 合肥-加劲 的测试，让本类库圆满完成。注意：M地址范围有限 0-31地址<br />
	/// 在本类的<see cref="T:HslCommunication.Profinet.Siemens.SiemensPPIOverTcp" />实现类里，如果使用了Async的异步方法，没有增加同步锁，多线程调用可能会引发数据错乱的情况。<br />
	/// In the <see cref="T:HslCommunication.Profinet.Siemens.SiemensPPIOverTcp" /> implementation class of this class, if the asynchronous method of Async is used, 
	/// the synchronization lock is not added, and multi-threaded calls may cause data disorder.
	/// </remarks>
	// Token: 0x0200004D RID: 77
	public class SiemensPPI : SerialDeviceBase
	{
		/// <summary>
		/// 实例化一个西门子的PPI协议对象<br />
		/// Instantiate a Siemens PPI protocol object
		/// </summary>
		// Token: 0x06000630 RID: 1584 RVA: 0x0001D6BD File Offset: 0x0001B8BD
		public SiemensPPI()
		{
			base.ByteTransform = new ReverseBytesTransform();
			base.WordLength = 2;
			this.communicationLock = new object();
		}

		/// <summary>
		/// 西门子PLC的站号信息<br />
		/// Siemens PLC station number information
		/// </summary>
		// Token: 0x17000143 RID: 323
		// (get) Token: 0x06000631 RID: 1585 RVA: 0x0001D6ED File Offset: 0x0001B8ED
		// (set) Token: 0x06000632 RID: 1586 RVA: 0x0001D6F5 File Offset: 0x0001B8F5
		public byte Station
		{
			get
			{
				return this.station;
			}
			set
			{
				this.station = value;
			}
		}

		/// <summary>
		/// 从西门子的PLC中读取数据信息，地址为"M100","AI100","I0","Q0","V100","S100"等<br />
		/// Read data information from Siemens PLC with addresses "M100", "AI100", "I0", "Q0", "V100", "S100", etc.
		/// </summary>
		/// <param name="address">西门子的地址数据信息</param>
		/// <param name="length">数据长度</param>
		/// <returns>带返回结果的结果对象</returns>
		// Token: 0x06000633 RID: 1587 RVA: 0x0001D700 File Offset: 0x0001B900
		[HslMqttApi("ReadByteArray", "")]
		public override OperateResult<byte[]> Read(string address, ushort length)
		{
			byte b = (byte)HslHelper.ExtractParameter(ref address, "s", (int)this.Station);
			OperateResult<byte[]> operateResult = SiemensPPIOverTcp.BuildReadCommand(b, address, length, false);
			bool flag = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				object obj = this.communicationLock;
				lock (obj)
				{
					OperateResult<byte[]> operateResult2 = base.ReadBase(operateResult.Content);
					bool flag3 = !operateResult2.IsSuccess;
					if (flag3)
					{
						result = operateResult2;
					}
					else
					{
						bool flag4 = operateResult2.Content[0] != 229;
						if (flag4)
						{
							result = new OperateResult<byte[]>("PLC Receive Check Failed:" + SoftBasic.ByteToHexString(operateResult2.Content, ' '));
						}
						else
						{
							OperateResult<byte[]> operateResult3 = base.ReadBase(SiemensPPIOverTcp.GetExecuteConfirm(b));
							bool flag5 = !operateResult3.IsSuccess;
							if (flag5)
							{
								result = operateResult3;
							}
							else
							{
								OperateResult operateResult4 = SiemensPPIOverTcp.CheckResponse(operateResult3.Content);
								bool flag6 = !operateResult4.IsSuccess;
								if (flag6)
								{
									result = OperateResult.CreateFailedResult<byte[]>(operateResult4);
								}
								else
								{
									byte[] array = new byte[(int)length];
									bool flag7 = operateResult3.Content[21] == byte.MaxValue && operateResult3.Content[22] == 4;
									if (flag7)
									{
										Array.Copy(operateResult3.Content, 25, array, 0, (int)length);
									}
									result = OperateResult.CreateSuccessResult<byte[]>(array);
								}
							}
						}
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 从西门子的PLC中读取bool数据信息，地址为"M100.0","AI100.1","I0.3","Q0.6","V100.4","S100"等<br />
		/// Read bool data information from Siemens PLC, the addresses are "M100.0", "AI100.1", "I0.3", "Q0.6", "V100.4", "S100", etc.
		/// </summary>
		/// <param name="address">西门子的地址数据信息</param>
		/// <param name="length">数据长度</param>
		/// <returns>带返回结果的结果对象</returns>
		// Token: 0x06000634 RID: 1588 RVA: 0x0001D880 File Offset: 0x0001BA80
		[HslMqttApi("ReadBoolArray", "")]
		public override OperateResult<bool[]> ReadBool(string address, ushort length)
		{
			byte b = (byte)HslHelper.ExtractParameter(ref address, "s", (int)this.Station);
			OperateResult<byte[]> operateResult = SiemensPPIOverTcp.BuildReadCommand(b, address, length, true);
			bool flag = !operateResult.IsSuccess;
			OperateResult<bool[]> result;
			if (flag)
			{
				result = OperateResult.CreateFailedResult<bool[]>(operateResult);
			}
			else
			{
				object obj = this.communicationLock;
				lock (obj)
				{
					OperateResult<byte[]> operateResult2 = base.ReadBase(operateResult.Content);
					bool flag3 = !operateResult2.IsSuccess;
					if (flag3)
					{
						result = OperateResult.CreateFailedResult<bool[]>(operateResult2);
					}
					else
					{
						bool flag4 = operateResult2.Content[0] != 229;
						if (flag4)
						{
							result = new OperateResult<bool[]>("PLC Receive Check Failed:" + SoftBasic.ByteToHexString(operateResult2.Content, ' '));
						}
						else
						{
							OperateResult<byte[]> operateResult3 = base.ReadBase(SiemensPPIOverTcp.GetExecuteConfirm(b));
							bool flag5 = !operateResult3.IsSuccess;
							if (flag5)
							{
								result = OperateResult.CreateFailedResult<bool[]>(operateResult3);
							}
							else
							{
								OperateResult operateResult4 = SiemensPPIOverTcp.CheckResponse(operateResult3.Content);
								bool flag6 = !operateResult4.IsSuccess;
								if (flag6)
								{
									result = OperateResult.CreateFailedResult<bool[]>(operateResult4);
								}
								else
								{
									byte[] array = new byte[operateResult3.Content.Length - 27];
									bool flag7 = operateResult3.Content[21] == byte.MaxValue && operateResult3.Content[22] == 3;
									if (flag7)
									{
										Array.Copy(operateResult3.Content, 25, array, 0, array.Length);
									}
									result = OperateResult.CreateSuccessResult<bool[]>(SoftBasic.ByteToBoolArray(array, (int)length));
								}
							}
						}
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 将字节数据写入到西门子PLC中，地址为"M100.0","AI100.1","I0.3","Q0.6","V100.4","S100"等<br />
		/// Write byte data to Siemens PLC with addresses "M100.0", "AI100.1", "I0.3", "Q0.6", "V100.4", "S100", etc.
		/// </summary>
		/// <param name="address">西门子的地址数据信息</param>
		/// <param name="value">数据长度</param>
		/// <returns>带返回结果的结果对象</returns>
		// Token: 0x06000635 RID: 1589 RVA: 0x0001DA24 File Offset: 0x0001BC24
		[HslMqttApi("WriteByteArray", "")]
		public override OperateResult Write(string address, byte[] value)
		{
			byte b = (byte)HslHelper.ExtractParameter(ref address, "s", (int)this.Station);
			OperateResult<byte[]> operateResult = SiemensPPIOverTcp.BuildWriteCommand(b, address, value);
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				object obj = this.communicationLock;
				lock (obj)
				{
					OperateResult<byte[]> operateResult2 = base.ReadBase(operateResult.Content);
					bool flag3 = !operateResult2.IsSuccess;
					if (flag3)
					{
						result = operateResult2;
					}
					else
					{
						bool flag4 = operateResult2.Content[0] != 229;
						if (flag4)
						{
							result = new OperateResult<byte[]>("PLC Receive Check Failed:" + operateResult2.Content[0].ToString());
						}
						else
						{
							OperateResult<byte[]> operateResult3 = base.ReadBase(SiemensPPIOverTcp.GetExecuteConfirm(b));
							bool flag5 = !operateResult3.IsSuccess;
							if (flag5)
							{
								result = operateResult3;
							}
							else
							{
								OperateResult operateResult4 = SiemensPPIOverTcp.CheckResponse(operateResult3.Content);
								bool flag6 = !operateResult4.IsSuccess;
								if (flag6)
								{
									result = operateResult4;
								}
								else
								{
									result = OperateResult.CreateSuccessResult();
								}
							}
						}
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 将bool数据写入到西门子PLC中，地址为"M100.0","AI100.1","I0.3","Q0.6","V100.4","S100"等<br />
		/// Write the bool data to Siemens PLC with the addresses "M100.0", "AI100.1", "I0.3", "Q0.6", "V100.4", "S100", etc.
		/// </summary>
		/// <param name="address">西门子的地址数据信息</param>
		/// <param name="value">数据长度</param>
		/// <returns>带返回结果的结果对象</returns>
		// Token: 0x06000636 RID: 1590 RVA: 0x0001DB48 File Offset: 0x0001BD48
		[HslMqttApi("WriteBoolArray", "")]
		public override OperateResult Write(string address, bool[] value)
		{
			byte b = (byte)HslHelper.ExtractParameter(ref address, "s", (int)this.Station);
			OperateResult<byte[]> operateResult = SiemensPPIOverTcp.BuildWriteCommand(b, address, value);
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				object obj = this.communicationLock;
				lock (obj)
				{
					OperateResult<byte[]> operateResult2 = base.ReadBase(operateResult.Content);
					bool flag3 = !operateResult2.IsSuccess;
					if (flag3)
					{
						result = operateResult2;
					}
					else
					{
						bool flag4 = operateResult2.Content[0] != 229;
						if (flag4)
						{
							result = new OperateResult<byte[]>("PLC Receive Check Failed:" + operateResult2.Content[0].ToString());
						}
						else
						{
							OperateResult<byte[]> operateResult3 = base.ReadBase(SiemensPPIOverTcp.GetExecuteConfirm(b));
							bool flag5 = !operateResult3.IsSuccess;
							if (flag5)
							{
								result = operateResult3;
							}
							else
							{
								OperateResult operateResult4 = SiemensPPIOverTcp.CheckResponse(operateResult3.Content);
								bool flag6 = !operateResult4.IsSuccess;
								if (flag6)
								{
									result = operateResult4;
								}
								else
								{
									result = OperateResult.CreateSuccessResult();
								}
							}
						}
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 从西门子的PLC中读取byte数据信息，地址为"M100","AI100","I0","Q0","V100","S100"等，详细请参照API文档<br />
		/// Read byte data information from Siemens PLC. The addresses are "M100", "AI100", "I0", "Q0", "V100", "S100", etc. Please refer to the API documentation for details.
		/// </summary>
		/// <param name="address">西门子的地址数据信息</param>
		/// <returns>带返回结果的结果对象</returns>
		// Token: 0x06000637 RID: 1591 RVA: 0x0001D13B File Offset: 0x0001B33B
		[HslMqttApi("ReadByte", "")]
		public OperateResult<byte> ReadByte(string address)
		{
			return ByteTransformHelper.GetResultFromArray<byte>(this.Read(address, 1));
		}

		/// <summary>
		/// 向西门子的PLC中读取byte数据，地址为"M100","AI100","I0","Q0","V100","S100"等，详细请参照API文档<br />
		/// Read byte data from Siemens PLC with addresses "M100", "AI100", "I0", "Q0", "V100", "S100", etc. For details, please refer to the API documentation
		/// </summary>
		/// <param name="address">西门子的地址数据信息</param>
		/// <param name="value">数据长度</param>
		/// <returns>带返回结果的结果对象</returns>
		// Token: 0x06000638 RID: 1592 RVA: 0x0001D14A File Offset: 0x0001B34A
		[HslMqttApi("Write", "")]
		public OperateResult Write(string address, byte value)
		{
			return this.Write(address, new byte[]
			{
				value
			});
		}

		/// <summary>
		/// 启动西门子PLC为RUN模式，参数信息可以携带站号信息 "s=2;", 注意，分号是必须的。<br />
		/// Start Siemens PLC in RUN mode, parameter information can carry station number information "s=2;", note that the semicolon is required.
		/// </summary>
		/// <param name="parameter">额外的参数信息，例如可以携带站号信息 "s=2;", 注意，分号是必须的。</param>
		/// <returns>是否启动成功</returns>
		// Token: 0x06000639 RID: 1593 RVA: 0x0001DC6C File Offset: 0x0001BE6C
		[HslMqttApi]
		public OperateResult Start(string parameter = "")
		{
			byte b = (byte)HslHelper.ExtractParameter(ref parameter, "s", (int)this.Station);
			byte[] array = new byte[]
			{
				104,
				33,
				33,
				104,
				0,
				0,
				108,
				50,
				1,
				0,
				0,
				0,
				0,
				0,
				20,
				0,
				0,
				40,
				0,
				0,
				0,
				0,
				0,
				0,
				253,
				0,
				0,
				9,
				80,
				95,
				80,
				82,
				79,
				71,
				82,
				65,
				77,
				170,
				22
			};
			array[4] = b;
			byte[] send = array;
			object obj = this.communicationLock;
			OperateResult result;
			lock (obj)
			{
				OperateResult<byte[]> operateResult = base.ReadBase(send);
				bool flag2 = !operateResult.IsSuccess;
				if (flag2)
				{
					result = operateResult;
				}
				else
				{
					bool flag3 = operateResult.Content[0] != 229;
					if (flag3)
					{
						result = new OperateResult<byte[]>("PLC Receive Check Failed:" + operateResult.Content[0].ToString());
					}
					else
					{
						OperateResult<byte[]> operateResult2 = base.ReadBase(SiemensPPIOverTcp.GetExecuteConfirm(b));
						bool flag4 = !operateResult2.IsSuccess;
						if (flag4)
						{
							result = operateResult2;
						}
						else
						{
							result = OperateResult.CreateSuccessResult();
						}
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 停止西门子PLC，切换为Stop模式，参数信息可以携带站号信息 "s=2;", 注意，分号是必须的。<br />
		/// Stop Siemens PLC and switch to Stop mode, parameter information can carry station number information "s=2;", note that the semicolon is required.
		/// </summary>
		/// <param name="parameter">额外的参数信息，例如可以携带站号信息 "s=2;", 注意，分号是必须的。</param>
		/// <returns>是否停止成功</returns>
		// Token: 0x0600063A RID: 1594 RVA: 0x0001DD60 File Offset: 0x0001BF60
		[HslMqttApi]
		public OperateResult Stop(string parameter = "")
		{
			byte b = (byte)HslHelper.ExtractParameter(ref parameter, "s", (int)this.Station);
			byte[] array = new byte[]
			{
				104,
				29,
				29,
				104,
				0,
				0,
				108,
				50,
				1,
				0,
				0,
				0,
				0,
				0,
				16,
				0,
				0,
				41,
				0,
				0,
				0,
				0,
				0,
				9,
				80,
				95,
				80,
				82,
				79,
				71,
				82,
				65,
				77,
				170,
				22
			};
			array[4] = b;
			byte[] send = array;
			object obj = this.communicationLock;
			OperateResult result;
			lock (obj)
			{
				OperateResult<byte[]> operateResult = base.ReadBase(send);
				bool flag2 = !operateResult.IsSuccess;
				if (flag2)
				{
					result = operateResult;
				}
				else
				{
					bool flag3 = operateResult.Content[0] != 229;
					if (flag3)
					{
						result = new OperateResult<byte[]>("PLC Receive Check Failed:" + operateResult.Content[0].ToString());
					}
					else
					{
						OperateResult<byte[]> operateResult2 = base.ReadBase(SiemensPPIOverTcp.GetExecuteConfirm(b));
						bool flag4 = !operateResult2.IsSuccess;
						if (flag4)
						{
							result = operateResult2;
						}
						else
						{
							result = OperateResult.CreateSuccessResult();
						}
					}
				}
			}
			return result;
		}

		/// <inheritdoc />
		// Token: 0x0600063B RID: 1595 RVA: 0x0001DE54 File Offset: 0x0001C054
		public override string ToString()
		{
			return string.Format("SiemensPPI[{0}:{1}]", base.PortName, base.BaudRate);
		}

		// Token: 0x040001A9 RID: 425
		private byte station = 2;

		// Token: 0x040001AA RID: 426
		private object communicationLock;
	}
}
